/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#ifdef __SSE2__
#include <emmintrin.h>
#endif

#if defined(__SSE__) && defined(__MMX__)
#include <xmmintrin.h>
#include <mmintrin.h>
#endif

#include "flgrCoreData.h"
#include "flgrCoreMalloc.h"
#include "flgrCoreDispatch.h"


int flgr1d_compare_eq_fast_fgUINT8(FLGR_Data1D *dat1, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  int i, nbvector = dat1->length/16;
  fgUINT8 array_cmp[16] __attribute__ ((aligned (16)));
  fgUINT8 *psrc1 = (fgUINT8*) dat1->array;
  fgUINT8 *psrc2 = (fgUINT8*) dat2->array;
  __m128i *vec_psrc1 = (__m128i*) dat1->array;
  __m128i *vec_psrc2 = (__m128i*) dat2->array;
  __m128i vectest,vectmp;
  fgUINT8 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_epi8(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_epi8(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si128(vectest,vectmp);
  }
  
  *((__m128i*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<16 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
#if defined(__MMX__) && (__SSE__)
  int i, nbvector = dat1->length/8;
  fgUINT8 array_cmp[8] __attribute__ ((aligned (16)));
  fgUINT8 *psrc1 = (fgUINT8*) dat1->array;
  fgUINT8 *psrc2 = (fgUINT8*) dat2->array;
  __m64 *vec_psrc1 = (__m64*) dat1->array;
  __m64 *vec_psrc2 = (__m64*) dat2->array;
  __m64 vectest,vectmp;
  fgUINT8 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_pi8(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_pi8(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si64(vectest,vectmp);
  }
  
  *((__m64*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<8 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
  FLGR_DECLARE_FUNCTION;
  POST_ERROR("SSE2 not activated\n");
  return FLGR_RET_NOT_IMPLEMENTED;
#endif
#endif
}


int flgr1d_compare_eq_fast_fgUINT16(FLGR_Data1D *dat1, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  int i, nbvector = dat1->length/8;
  fgUINT16 array_cmp[8] __attribute__ ((aligned (16)));
  fgUINT16 *psrc1 = (fgUINT16*) dat1->array;
  fgUINT16 *psrc2 = (fgUINT16*) dat2->array;
  __m128i *vec_psrc1 = (__m128i*) dat1->array;
  __m128i *vec_psrc2 = (__m128i*) dat2->array;
  __m128i vectest,vectmp;
  fgUINT16 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_epi16(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_epi16(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si128(vectest,vectmp);
  }
  
  *((__m128i*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<8 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
#if defined(__MMX__) && (__SSE__)
  int i, nbvector = dat1->length/4;
  fgUINT16 array_cmp[8] __attribute__ ((aligned (16)));
  fgUINT16 *psrc1 = (fgUINT16*) dat1->array;
  fgUINT16 *psrc2 = (fgUINT16*) dat2->array;
  __m64 *vec_psrc1 = (__m64*) dat1->array;
  __m64 *vec_psrc2 = (__m64*) dat2->array;
  __m64 vectest,vectmp;
  fgUINT16 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_pi16(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_pi16(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si64(vectest,vectmp);
  }
  
  *((__m64*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<4 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
  FLGR_DECLARE_FUNCTION;
  POST_ERROR("SSE/SSE2 not activated\n");
  return FLGR_RET_NOT_IMPLEMENTED;
#endif
#endif
}

 
int flgr1d_compare_eq_fast_fgUINT32(FLGR_Data1D *dat1, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  int i, nbvector = dat1->length/4;
  fgUINT32 array_cmp[4] __attribute__ ((aligned (16)));
  fgUINT32 *psrc1 = (fgUINT32*) dat1->array;
  fgUINT32 *psrc2 = (fgUINT32*) dat2->array;
  __m128i *vec_psrc1 = (__m128i*) dat1->array;
  __m128i *vec_psrc2 = (__m128i*) dat2->array;
  __m128i vectest,vectmp;
  fgUINT32 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_epi32(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_epi32(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si128(vectest,vectmp);
  }
  
  *((__m128i*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<4 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
#if defined(__MMX__) && (__SSE__)
  int i, nbvector = dat1->length/2;
  fgUINT32 array_cmp[8] __attribute__ ((aligned (16)));
  fgUINT32 *psrc1 = (fgUINT32*) dat1->array;
  fgUINT32 *psrc2 = (fgUINT32*) dat2->array;
  __m64 *vec_psrc1 = (__m64*) dat1->array;
  __m64 *vec_psrc2 = (__m64*) dat2->array;
  __m64 vectest,vectmp;
  fgUINT32 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_pi32(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_pi32(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si64(vectest,vectmp);
  }
  
  *((__m64*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<2; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
  FLGR_DECLARE_FUNCTION;
  POST_ERROR("SSE/SSE2 not activated\n");
  return FLGR_RET_NOT_IMPLEMENTED;
#endif
#endif
}



int flgr1d_compare_eq_fast_fgINT8(FLGR_Data1D *dat1, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  int i, nbvector = dat1->length/16;
  fgINT8 array_cmp[16] __attribute__ ((aligned (16)));
  fgINT8 *psrc1 = (fgINT8*) dat1->array;
  fgINT8 *psrc2 = (fgINT8*) dat2->array;
  __m128i *vec_psrc1 = (__m128i*) dat1->array;
  __m128i *vec_psrc2 = (__m128i*) dat2->array;
  __m128i vectest,vectmp;
  fgINT8 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_epi8(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_epi8(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si128(vectest,vectmp);
  }
  
  *((__m128i*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<16 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
#if defined(__MMX__) && (__SSE__)
  int i, nbvector = dat1->length/8;
  fgINT8 array_cmp[8] __attribute__ ((aligned (16)));
  fgINT8 *psrc1 = (fgINT8*) dat1->array;
  fgINT8 *psrc2 = (fgINT8*) dat2->array;
  __m64 *vec_psrc1 = (__m64*) dat1->array;
  __m64 *vec_psrc2 = (__m64*) dat2->array;
  __m64 vectest,vectmp;
  fgINT8 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_pi8(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_pi8(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si64(vectest,vectmp);
  }
  
  *((__m64*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<8 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
  FLGR_DECLARE_FUNCTION;
  POST_ERROR("SSE2 not activated\n");
  return FLGR_RET_NOT_IMPLEMENTED;
#endif
#endif 
}


int flgr1d_compare_eq_fast_fgINT16(FLGR_Data1D *dat1, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  int i, nbvector = dat1->length/8;
  fgINT16 array_cmp[8] __attribute__ ((aligned (16)));
  fgINT16 *psrc1 = (fgINT16*) dat1->array;
  fgINT16 *psrc2 = (fgINT16*) dat2->array;
  __m128i *vec_psrc1 = (__m128i*) dat1->array;
  __m128i *vec_psrc2 = (__m128i*) dat2->array;
  __m128i vectest,vectmp;
  fgINT16 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_epi16(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_epi16(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si128(vectest,vectmp);
  }
  
  *((__m128i*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<8 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
#if defined(__MMX__) && (__SSE__)
  int i, nbvector = dat1->length/4;
  fgINT16 array_cmp[8] __attribute__ ((aligned (16)));
  fgINT16 *psrc1 = (fgINT16*) dat1->array;
  fgINT16 *psrc2 = (fgINT16*) dat2->array;
  __m64 *vec_psrc1 = (__m64*) dat1->array;
  __m64 *vec_psrc2 = (__m64*) dat2->array;
  __m64 vectest,vectmp;
  fgINT16 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_pi16(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_pi16(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si64(vectest,vectmp);
  }
  
  *((__m64*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<4 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;
#else
  FLGR_DECLARE_FUNCTION;
  POST_ERROR("SSE/SSE2 not activated\n");
  return FLGR_RET_NOT_IMPLEMENTED;
#endif
#endif
}

 
int flgr1d_compare_eq_fast_fgINT32(FLGR_Data1D *dat1, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  int i, nbvector = dat1->length/4;
  fgINT32 array_cmp[4] __attribute__ ((aligned (16)));
  fgINT32 *psrc1 = (fgINT32*) dat1->array;
  fgINT32 *psrc2 = (fgINT32*) dat2->array;
  __m128i *vec_psrc1 = (__m128i*) dat1->array;
  __m128i *vec_psrc2 = (__m128i*) dat2->array;
  __m128i vectest,vectmp;
  fgINT32 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_epi32(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_epi32(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si128(vectest,vectmp);
  }
  
  *((__m128i*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<4 ; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
#if defined(__MMX__) && (__SSE__)
  int i, nbvector = dat1->length/2;
  fgINT32 array_cmp[8] __attribute__ ((aligned (16)));
  fgINT32 *psrc1 = (fgINT32*) dat1->array;
  fgINT32 *psrc2 = (fgINT32*) dat2->array;
  __m64 *vec_psrc1 = (__m64*) dat1->array;
  __m64 *vec_psrc2 = (__m64*) dat2->array;
  __m64 vectest,vectmp;
  fgINT32 cmp;
  
  FLGR_DECLARE_FUNCTION;

  i=dat1->length;
  psrc1[i]=0;psrc2[i++]=0;psrc1[i]=0;psrc2[i++]=0;
 
  vectest = _mm_cmpeq_pi32(vec_psrc1[0], vec_psrc2[0]);
  for(i=1 ; i<=nbvector ; i++) {
    vectmp = _mm_cmpeq_pi32(vec_psrc1[i], vec_psrc2[i]);
    vectest = _mm_and_si64(vectest,vectmp);
  }
  
  *((__m64*) array_cmp) = vectest;

  cmp = (array_cmp[0] != 0);

  for(i=1 ; i<2; i++) {
    cmp &= (array_cmp[i] != 0);
  }

  if(cmp != 0) 
    return FLGR_TRUE;
  else 
    return FLGR_FALSE;

#else
  FLGR_DECLARE_FUNCTION;
  POST_ERROR("SSE/SSE2 not activated\n");
  return FLGR_RET_NOT_IMPLEMENTED;
#endif
#endif
}



//! @}
